﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Data;
using System.Drawing;

namespace MyChart
{
    /// <summary>
    /// 图表控件数据项集合抽象基类（数据项管理器）
    /// </summary>
    public abstract class ItemManager : IXmlGeneratable
    {
        #region 字段

        private FusionChart _chart;

        private Dictionary<int, Dictionary<int, List<string>>> _dictArguments = new Dictionary<int, Dictionary<int, List<string>>>();
        private Dictionary<string, string> _extendAttributes = new Dictionary<string, string>();

        #endregion

        #region 属性

        /// <summary>
        /// 获取或设置数据集合所属的图表控件
        /// </summary>
        public FusionChart Chart
        {
            get { return _chart; }
            set { _chart = value; }
        }

        /// <summary>
        /// 获取或设置数据项集合Xml配置字符串的临时扩展属性
        /// </summary>
        public Dictionary<string, string> ExtendAttributes
        {
            get { return _extendAttributes; }
            set { _extendAttributes = value; }
        }

        /// <summary>
        /// 获取或设置参数列表，第一个int为组的序列，第二个为项的序列，然后是参数列表
        /// </summary>
        public Dictionary<int, Dictionary<int, List<string>>> DictArguments
        {
            get { return _dictArguments; }
            set { _dictArguments = value; }
        }

        #endregion

        #region 构造器

        /// <summary>
        /// 初始化 ItemManager 类
        /// </summary>
        /// <param name="chart">关联数据项集合的控件实例</param>
        public ItemManager(FusionChart chart)
        {
            _chart = chart;
        }

        #endregion

        #region 抽象属性

        /// <summary>
        /// 获取当前数据集合是否为空
        /// </summary>
        public abstract bool IsEmpty
        {
            get;
        }

        #endregion

        #region 抽象方法

        /// <summary>
        /// 要求子类实现的获取当前集合对应的 FusionChart Xml配置字符串方法
        /// </summary>
        /// <returns>Xml配置字符串</returns>
        public abstract string GetXmlString();

        #endregion

        #region 方法

        /// <summary>
        /// 获取指定数据项弹出提示的已格式化字符串
        /// </summary>
        /// <param name="row">对应的数据行</param>
        /// <param name="toolText">输出参数，返回的已格式化字符串</param>
        /// <returns>如果成功格式化（已设置格式化字符串，并且当前数据项绑定了数据行），则为 true；否则为 false</returns>
        public bool GetFormattedToolText(DataRowView row, out string toolText)
        {
            return GetFormattedToolText(_chart.ToolTextFormat, row, out toolText);
        }
        /// <summary>
        /// 获取指定数据项弹出提示的已格式化字符串
        /// </summary>
        /// <param name="row">toolText模板</param>
        /// <param name="row">对应的数据行</param>
        /// <param name="toolText">输出参数，返回的已格式化字符串</param>
        /// <returns>如果成功格式化（已设置格式化字符串，并且当前数据项绑定了数据行），则为 true；否则为 false</returns>
        public bool GetFormattedToolText(string sToolTextFormat, DataRowView row, out string toolText)
        {
            if (sToolTextFormat.Trim() != "" && row != null)
            {
                toolText = sToolTextFormat.Trim();
                //创建正则表达式，搜索{DataFiled}格式字符
                Regex reg = new Regex("{(.+?)}");
                MatchCollection matchList = reg.Matches(toolText);
                foreach (Match match in matchList)
                {
                    //如果匹配结果中包含冒号则进行指定格式化
                    //否则判断值是否是数字
                    //      如果是，则格式化为指定四舍五入精度的数字
                    //      否则直接输出
                    if (match.Groups[1].Value.Contains(':'))
                    {
                        string field = match.Groups[1].Value.Split(':')[0];
                        string format = match.Groups[1].Value.Split(':')[1];

                        decimal value;
                        if (decimal.TryParse(row[field].ToString(), out value))
                        {
                            toolText = toolText.Replace(match.Groups[0].Value, string.Format("{0:" + format + "}", value));
                        }
                        else
                        {
                            toolText = toolText.Replace(match.Groups[0].Value, string.Format("{0:" + format + "}", row[field]));
                        }
                    }
                    else
                    {
                        decimal value;
                        if (decimal.TryParse(row[match.Groups[1].Value].ToString(), out value))
                        {
                            toolText = toolText.Replace(match.Groups[0].Value, string.Format("{0:N" + Chart.Decimals + "}", value));
                        }
                        else
                        {
                            toolText = toolText.Replace(match.Groups[0].Value, row[match.Groups[1].Value].ToString());
                        }
                    }
                }
                return true;
            }
            else
            {
                toolText = "";
                return false;
            }
        }
        /// <summary>
        /// 获取已格式化的客户端点击事件脚本代码
        /// </summary>
        /// <param name="row">对应的数据行</param>
        /// <param name="iSeriesIndex">当前数据项所属的序列，如果实单数据项，则序列编号从0开始</param>
        /// <param name="iItemIndex">当前组的数据项编号</param>
        /// <param name="scriptText">输出已格式化的客户端点击事件脚本代码</param>
        /// <returns>是否有格式化的事件代码，有则为 true；否则为 false</returns>
        public bool GetFormattedScriptText(DataRowView row, int iSeriesIndex, int iItemIndex, out string scriptText)
        {
            return GetFormattedScriptText(_chart.OnClientClick, row, iSeriesIndex, iItemIndex, out scriptText);
        }
        /// <summary>
        /// 获取已格式化的客户端点击事件脚本代码
        /// </summary>
        /// <param name="sOnClientClick">OnClientClick事件模板</param>
        /// <param name="row">对应的数据行</param>
        /// <param name="iSeriesIndex">当前数据项所属的序列，如果实单数据项，则序列编号从0开始</param>
        /// <param name="iItemIndex">当前组的数据项编号</param>
        /// <param name="scriptText">输出已格式化的客户端点击事件脚本代码</param>
        /// <returns>是否有格式化的事件代码，有则为 true；否则为 false</returns>
        public bool GetFormattedScriptText(string sOnClientClick, DataRowView row, int iSeriesIndex, int iItemIndex, out string scriptText)
        {
            if (!string.IsNullOrEmpty(sOnClientClick) && row != null)
            {
                scriptText = sOnClientClick.Trim();
                int iFuncIndex = scriptText.IndexOf('('); //函数名称的位置
                string clickMethodName = iFuncIndex > 0 ? sOnClientClick.Substring(0, iFuncIndex) : scriptText;

                int iArgsIndex = 0;
                string sArgs = string.Empty;
                Regex reg = new Regex("{(.+?)}");
                MatchCollection matchList = reg.Matches(scriptText);

                if (!_dictArguments.ContainsKey(iSeriesIndex))
                {
                    _dictArguments[iSeriesIndex] = new Dictionary<int, List<string>>();
                }
                if (!_dictArguments[iSeriesIndex].ContainsKey(iItemIndex))
                {
                    _dictArguments[iSeriesIndex][iItemIndex] = new List<string>();
                }

                foreach (Match match in matchList)
                {
                    sArgs += string.Format("__{0}_{1}_{2}_args{3},", _chart.ClientID, iSeriesIndex, iItemIndex, iArgsIndex);
                    iArgsIndex++;

                    string field = match.Groups[1].Value;
                    _dictArguments[iSeriesIndex][iItemIndex].Add(row[field].ToString());
                }

                if (sArgs.Length > 0)
                {
                    sArgs = sArgs.Remove(sArgs.Length - 1, 1);
                }
                scriptText = string.Format("javascript:if(typeof {0} != _Undefined){{{0}({1});}}else{{alert(_UndefinedTip)}}", clickMethodName, sArgs);

                return true;
            }
            else
            {
                scriptText = string.Empty;
                return false;
            }
        }
        #endregion
    }
}
